class Port {
  Mod parent;
  Plug plug;
  float bx, by;
  int type, index, nameAlpha, ws, indexOff;
  String name;
  Boolean selected;
  Boolean anyIn, isUsed, showUnused, addPort, showIndex, trigger, feed;

  Port(Mod tempParent, int tempType, String tempName) {
    parent=tempParent;
    type=tempType;
    nameAlpha=0;
    showUnused=false;
    addPort=false;
    showIndex=false;
    indexOff=0;
    trigger=false;
    feed=false;

    if (tempType==0) {
      anyIn=true;
    }
    else {
      anyIn=false;
    }
    name=tempName;
    selected=false;
    if(type==3){
      plug=new Plug(ac);
    }
  }

  void setAddPort(Boolean tempFlag) {
    addPort=tempFlag;
  }
  void setShowIndex(Boolean tempFlag) {
    showIndex=tempFlag;
  }
  void drawPort(PGraphics canvas, float tempX, float tempY, int tempI) {
    if (parent.selected) {
      canvas.fill(150);
    }
    else {
      canvas.fill(100);
    }

    canvas.noStroke();
    
      if (parent.wy<=2*r) {
        if (feed){
          canvas.arc(bx+tempX, by+tempY, r+3, r+3, PI, TWO_PI);
        }else if (tempI!=1) {
          canvas.arc(bx+tempX, by+tempY, r+3, r+3, PI/2, TWO_PI-PI/2);
        }
        else {
          canvas.arc(bx+tempX, by+tempY, r+3, r+3, TWO_PI-PI/2+0.5, TWO_PI+PI/2-0.5);
        }
      }
      else {
        if (feed){
          canvas.arc(bx+tempX, by+tempY, r+3, r+3, PI-0.4, TWO_PI+0.4);
        }else if (tempI!=1) {
          canvas.arc(bx+tempX, by+tempY, r+3, r+3, PI/2-0.4, TWO_PI-PI/2+0.4);
        }
        else {
          canvas.arc(bx+tempX, by+tempY, r+3, r+3, TWO_PI-PI/2-0.2, TWO_PI+PI/2+0.2);
        }
      }
    
    if (nameAlpha>=0) {
      canvas.fill(255, 255, 100, nameAlpha);
      if (tempI!=0) {
        canvas.textAlign(RIGHT);
        canvas.text(name, bx+tempX-4*((tempI*2)-1), by+tempY-5);
      }
      else
      {
        canvas.textAlign(LEFT);
        canvas.text(name, bx+tempX-4*((tempI*2)-1), by+tempY-5);
      }
      nameAlpha=nameAlpha-5;
    }
    canvas.fill(sysCl[type]);



    canvas.noStroke();  
    canvas.ellipse(bx+tempX, by+tempY, r-2, r-2);

    if (((tempI==1 && !isUsed)||(tempI==0 && ws==0)) && showUnused) {
      canvas.fill(100);
      canvas.ellipse(bx+tempX, by+tempY, r-7, r-7);
    }
    /*if (addPort) {
     canvas.fill(100);
     canvas.ellipse(bx+tempX, by+tempY, r-6, r-6);
     }*/
  }
  void drawPortClick(PGraphics click, float tempX, float tempY, int parent) {
    click.noSmooth();
    click.fill(parent, index, 0);
    click.stroke(parent, index, 0);
    click.strokeWeight(6);
    click.ellipse(bx+tempX, by+tempY, r+1, r+1);
  }
  void setShowUnused(Boolean TempFlag) {
    showUnused=TempFlag;
  }

  float getBx() {
    return bx;
  }
  float getBy() {
    return by;
  }
  int getType() {
    return type;
  }
  String getName() {
    return name;
  }
  void setName(String tempName) {
    name=tempName;
  }
}

class outPort extends Port
{
  Wire[] wires;
  int[] stack;
  outPort(Mod tempParent, int tempType, String tempName) {
    super(tempParent, tempType, tempName);
    index=parent.op+1;
    parent.op++;
    wires=new Wire[255];
    ws=0;
  }
  void addWire(inPort tempEnd) {
    wires[ws]=new Wire(this, tempEnd, ws);
    tempEnd.inWire=wires[ws];
    ws++;
    tempEnd.isUsed=true;

    if (type==3) {
      addInputTo(tempEnd);
    }
  }
  void delWire(int tempIndex) {
    wires[tempIndex].end.isUsed=false;
    if (type==3) {
      removeInputFrom(wires[tempIndex].end);
    }
    if (wires[tempIndex].end.anyIn) {
      wires[tempIndex].end.type=0;
      wires[tempIndex].end.parent.callOnEdit();
    }
    wires[tempIndex].end.floatV=0;
    wires[tempIndex].end.stringV=null;
    wires[tempIndex].end.parent.update(wires[tempIndex].end.index);



    if (ws-1 > tempIndex) {
      for (int del=tempIndex+1; del<ws;del++) {
        wires[del-1]=wires[del];
      }
    }

    selected=false;
    ws--;
    if (wires[tempIndex].end.addPort) {
      wires[tempIndex].end.parent.remPort(wires[tempIndex].end.index-128, 0);
    }
    else if (parent.parent.hideUnusedPorts) {
      wires[tempIndex].end.parent.updatePorts();
    }
    if (addPort) {
      parent.remPort(index, 1);
    }
    else if (parent.parent.hideUnusedPorts) {
      parent.updatePorts();
    }
    if (ws==0 && anyIn) {
      type=0;
      parent.callOnEdit();
    }
  }
  void addInputTo(inPort tempIn) {
    tempIn.plug.addInput(plug);
  }
  void removeInputFrom(inPort tempIn) {
    tempIn.plug.removeConnection(0, plug, 0);
  }
  boolean isConnected(int tempMod, int tempPort) {
    Boolean isCon=false;

    if (ws!=0) {
      int check=0;
      do {

        if (wires[check].end.parent.index==tempMod && wires[check].end.index==tempPort)isCon=true;
        check++;
      }
      while (check<ws && !isCon);
    }
    return isCon;
  }
}

class inPort extends Port
{
  String stringV;
  String[] stringAV;
  String[][] string2DV;
  float floatV;
  float[] floatAV;
  float[][] float2DV;
  Wire inWire;
  //Boolean addPort;
  //int[] pp;

  inPort(Mod tempParent, int tempType, String tempName) {
    super(tempParent, tempType, tempName);
    index=parent.ip+129;
    parent.ip++;
    isUsed=false;
    //pp=new int[3];
    ws=0;
    //showUnused=false;
    //trigger=true;
  }

  void setString(String tempM) {
    stringV=tempM;
  }
  void setFloat(float tempM) {
    floatV=tempM;
    parent.update(index);
  }
}



